package com.alogic.cert.xscript;

import com.alogic.cert.*;
import com.alogic.xscript.ExecuteWatcher;
import com.alogic.xscript.Logiclet;
import com.alogic.xscript.LogicletContext;
import com.alogic.xscript.doc.XsObject;
import com.anysoft.util.Properties;
import com.anysoft.util.PropertiesConstants;
import org.apache.commons.lang3.StringUtils;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.Stack;

/**
 * 以指定证书的根证书来创建一个证书链
 *
 * @since 1.6.13.40 [20210306 duanyy] <br>
 */
public class CertChain extends NS{
    protected String cid = "$cert";

    /**
     * 证书
     */
    protected String $cert;

    /**
     * 私钥
     */
    protected String $key;

    protected String $keyPassword;

    public CertChain(String tag, Logiclet p) {
        super(tag, p);
    }

    @Override
    public void configure(Properties p){
        super.configure(p);

        $cert = PropertiesConstants.getRaw(p,"cert","");
        $key = PropertiesConstants.getRaw(p,"key","");
        $keyPassword = PropertiesConstants.getRaw(p,"keyPass","");
        cid = PropertiesConstants.getString(p, "cid", cid,true);
    }

    @Override
    protected void onExecute(XsObject root, XsObject current, LogicletContext ctx, ExecuteWatcher watcher) {
        CertificateStore store = CertificateStoreFactory.getDefault();
        CertificateContent pem = new PemCertificateContent();
        String cert = PropertiesConstants.transform(ctx,$cert,"");
        String key = PropertiesConstants.transform(ctx,$key,"");
        if (StringUtils.isEmpty(cert) || StringUtils.isEmpty(key)){
            //如果没有指定证书和私钥内容，则取系统根证书
            pem = store.getRoot(pem);
        }else{
            X509Certificate certificate = CertTools.loadX509Certificate(cert);
            PrivateKey privateKey = CertTools.loadPrivateKey(key,PropertiesConstants.transform(ctx,$keyPassword,""));
            if (certificate != null && privateKey != null){
                pem.setContent(String.valueOf(certificate.getSerialNumber()),certificate,privateKey);
            }else{
                pem = store.getRoot(pem);
            }
        }

        Stack<CertificateContent> stack = new Stack<CertificateContent>();
        stack.add(pem);
        try {
            ctx.setObject(cid, stack);
            super.onExecute(root, current, ctx, watcher);
        }finally{
            ctx.removeObject(cid);
        }
    }
}
